package com.ccrfid.rmc6.service.sys;

import com.ccrfid.rmc6.appconfig.exception.pojo.AppException;
import com.ccrfid.rmc6.appconfig.exception.pojo.CustomErrors;
import com.ccrfid.rmc6.entity.sys.AppModuleEntity;
import com.ccrfid.rmc6.entity.sys.RoleEntity;
import com.ccrfid.rmc6.entity.sys.RoleModuleRelation;
import com.ccrfid.rmc6.pojo.dto.sys.AppModuleDto;
import com.ccrfid.rmc6.repository.search.SearchCriteria;
import com.ccrfid.rmc6.repository.sys.AccountRoleRelationRepository;
import com.ccrfid.rmc6.repository.sys.AppModuleRepository;
import com.ccrfid.rmc6.repository.sys.RoleModuleRelationRepository;
import com.ccrfid.rmc6.repository.sys.RoleRepository;
import com.ccrfid.rmc6.resource.auth.pojo.UserPrincipal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class RoleServiceImpl implements RoleService {
    private static final Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private AccountRoleRelationRepository accountRoleRelationRepository;
    @Autowired
    private RoleModuleRelationRepository roleModuleRelationRepository;
    @Autowired
    private AppModuleRepository appModuleRepository;

    @Override
    public Page<RoleEntity> getRolePage(SearchCriteria criteria, Pageable pageable) {
        return roleRepository.search(criteria, pageable);
    }

    @Override
    public List<RoleEntity> getRoleList() {
        return roleRepository.getAllBy();
    }

    @Override
    public RoleEntity getRole(Long roleId) {
        RoleEntity roleEntity = roleRepository.getById(roleId);
        return roleEntity;
    }

    @Override
    public RoleEntity createRole(RoleEntity entity) throws AppException {
        if (entity.getRoleName() != null && roleRepository.existsByRoleName(entity.getRoleName())) {
            throw new AppException(Response.Status.CONFLICT.getStatusCode(),
                    CustomErrors.role_name_conflict.getCode(), CustomErrors.role_name_conflict.getReason(), "");
        }
        RoleEntity roleEntity = roleRepository.save(entity);
        return roleEntity;
    }

    @Override
    public RoleEntity updateRole(Long roleId, RoleEntity entity) throws AppException {
        if (!roleRepository.existsById(roleId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        if (!roleId.equals(entity.getId())) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.different_args.getCode(), CustomErrors.different_args.getReason(), "");
        }
        if (entity.getRoleName() != null && roleRepository.existsByRoleNameAndIdNot(entity.getRoleName(), roleId)) {
            throw new AppException(Response.Status.CONFLICT.getStatusCode(),
                    CustomErrors.role_name_conflict.getCode(), CustomErrors.role_name_conflict.getReason(), "");
        }
        //roleId.equals(1L)：内置管理员角色不可修改
        if (roleId.equals(1L)) {
            return roleRepository.getById(roleId);
        }
        return roleRepository.save(entity);
    }

    @Override
    public int deleteRoles(List<Long> idList) {
        int count = 0;
        for (Long roleId : idList) {
            //roleId.equals(1L)：内置管理员角色不可删除
            if (!roleId.equals(1L) && roleRepository.existsById(roleId)) {
                //1.删除账号-角色关联
                accountRoleRelationRepository.deleteByRoleId(roleId);
                //2.删除角色-应用模块关联
                roleModuleRelationRepository.deleteAllByRoleId(roleId);
                //3.删除角色
                roleRepository.deleteById(roleId);

                count++;
            }
        }
        return count;
    }

    @Override
    public List<AppModuleEntity> getAppModules(Long roleId, UserPrincipal userPrincipal) throws AppException {
        if (!roleRepository.existsById(roleId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        List<Long> roleIdList = userPrincipal.getRoles();
        if (roleIdList != null && roleIdList.size() > 0) {
            //1.获取登陆账号所拥有的模块信息
            List<RoleModuleRelation> accountRoleModuleRelationList = roleModuleRelationRepository.getAllByRoleIdIn(roleIdList);
            if (accountRoleModuleRelationList != null && accountRoleModuleRelationList.size() > 0) {
                Set<Long> accountModuleIdSet = new HashSet<>();
                for (RoleModuleRelation relation : accountRoleModuleRelationList) {
                    accountModuleIdSet.add(relation.getModuleId());
                }
                //2.获取某个特定角色所拥有的模块信息
                List<RoleModuleRelation> roleModuleRelationList = roleModuleRelationRepository.getAllByRoleId(roleId);
                if (roleModuleRelationList != null && roleModuleRelationList.size() > 0) {
                    Set<Long> roleModuleIdSet = new HashSet<>();
                    for (RoleModuleRelation relation : roleModuleRelationList) {
                        roleModuleIdSet.add(relation.getModuleId());
                    }
                    //3.求取两者的模块信息的交集
                    Set<Long> intersectionSet = new HashSet<>();
                    for (Long moduleId : roleModuleIdSet) {
                        if (accountModuleIdSet.contains(moduleId)) {
                            intersectionSet.add(moduleId);
                        }
                    }
                    //4.结果
                    return appModuleRepository.getAllByEnabledAndIdInOrderBySortNumber(1, intersectionSet);
                }
            }
        }
        return new ArrayList<>();
    }

    @Override
    public List<AppModuleDto> getAppModules2(Long roleId, UserPrincipal userPrincipal) throws AppException {
        if (!roleRepository.existsById(roleId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        List<AppModuleDto> list = new ArrayList<>();
        List<Long> roleIdList = userPrincipal.getRoles();
        if (roleIdList != null && roleIdList.size() > 0) {
            //1.获取登陆账号所拥有的模块信息
            List<RoleModuleRelation> accountRoleModuleRelationList = roleModuleRelationRepository.getAllByRoleIdIn(roleIdList);
            if (accountRoleModuleRelationList != null && accountRoleModuleRelationList.size() > 0) {
                Set<Long> accountModuleIdSet = new HashSet<>();
                for (RoleModuleRelation relation : accountRoleModuleRelationList) {
                    accountModuleIdSet.add(relation.getModuleId());
                }
                //2.获取某个特定角色所拥有的模块信息
                List<RoleModuleRelation> roleModuleRelationList = roleModuleRelationRepository.getAllByRoleId(roleId);
                if (roleModuleRelationList != null && roleModuleRelationList.size() > 0) {
                    Set<Long> roleModuleIdSet = new HashSet<>();
                    for (RoleModuleRelation relation : roleModuleRelationList) {
                        roleModuleIdSet.add(relation.getModuleId());
                    }
                    //3.求取两者的模块信息的交集
                    Set<Long> intersectionSet = new HashSet<>();
                    for (Long moduleId : roleModuleIdSet) {
                        if (accountModuleIdSet.contains(moduleId)) {
                            intersectionSet.add(moduleId);
                        }
                    }
                    //4.结果
                    List<AppModuleEntity> moduleEntityList =
                            appModuleRepository.getAllByEnabledAndIdInAndPidIsNullOrderBySortNumber(1, intersectionSet);
                    if (moduleEntityList != null && moduleEntityList.size() > 0) {
                        for (AppModuleEntity moduleEntity : moduleEntityList) {
                            list.add(getAppModuleDto(moduleEntity, intersectionSet));
                        }
                    }
                }
            }
        }
        return list;
    }

    private AppModuleDto getAppModuleDto(AppModuleEntity appModuleEntity, Set<Long> moduleIdSet) {
        AppModuleDto dto = new AppModuleDto();
        dto.setModule(appModuleEntity);
        List<AppModuleDto> subModuleDtoList = new ArrayList<>();
        List<AppModuleEntity> moduleEntityList =
                appModuleRepository.getAllByEnabledAndIdInAndPidOrderBySortNumber(1, moduleIdSet, appModuleEntity.getId());
        if (moduleEntityList != null && moduleEntityList.size() > 0) {
            for (AppModuleEntity moduleEntity : moduleEntityList) {
                subModuleDtoList.add(getAppModuleDto(moduleEntity, moduleIdSet));
            }
        }
        dto.setSubModules(subModuleDtoList);
        return dto;
    }

    @Override
    public void updateRoleModuleList(Long roleId, UserPrincipal userPrincipal, List<Long> moduleIdList) throws AppException {
        if (!roleRepository.existsById(roleId)) {
            throw new AppException(Response.Status.NOT_FOUND.getStatusCode(),
                    CustomErrors.resource_not_found.getCode(), CustomErrors.resource_not_found.getReason(), "");
        }
        if (moduleIdList == null) {
            throw new AppException(Response.Status.BAD_REQUEST.getStatusCode(),
                    CustomErrors.param_is_null.getCode(), CustomErrors.param_is_null.getReason(), "");
        }
        //roleId.equals(1L)：内置管理员角色不可修改
        if (roleId.equals(1L)) {
            return;
        }
        //1.获取登陆账号所拥有的模块信息
        List<Long> roleIdList = userPrincipal.getRoles();
        if (roleIdList != null && roleIdList.size() > 0) {
            List<RoleModuleRelation> accountRoleModuleRelationList = roleModuleRelationRepository.getAllByRoleIdIn(roleIdList);
            if (accountRoleModuleRelationList != null && accountRoleModuleRelationList.size() > 0) {
                Set<Long> accountModuleIdSet = new HashSet<>();
                for (RoleModuleRelation relation : accountRoleModuleRelationList) {
                    accountModuleIdSet.add(relation.getModuleId());
                }
                //2.获取某个特定角色所拥有的模块信息
                List<RoleModuleRelation> roleModuleRelationList = roleModuleRelationRepository.getAllByRoleId(roleId);
                if (roleModuleRelationList != null && roleModuleRelationList.size() > 0) {
                    //2.1 进行增量式调整
                    Set<Long> roleModuleIdSet = new HashSet<>();
                    for (RoleModuleRelation relation : roleModuleRelationList) {
                        roleModuleIdSet.add(relation.getModuleId());
                    }
                    //2.1.1.求取两者的模块信息的交集
                    Set<Long> intersectionModuleIdSet = new HashSet<>();
                    for (Long moduleId : roleModuleIdSet) {
                        if (accountModuleIdSet.contains(moduleId)) {
                            intersectionModuleIdSet.add(moduleId);
                        }
                    }
                    //2.1.2.删除旧关系：交集中存在，但是提交模块id列表中不存在
                    for (Long moduleId : intersectionModuleIdSet) {
                        if (!moduleIdList.contains(moduleId)) {
                            roleModuleRelationRepository.deleteAllByRoleIdAndModuleId(roleId, moduleId);
                        }
                    }
                    //2.1.3.添加新关系
                    for (Long moduleId : moduleIdList) {
                        if (!roleModuleRelationRepository.existsByRoleIdAndModuleId(roleId, moduleId)) {
                            RoleModuleRelation roleModuleRelation = new RoleModuleRelation();
                            roleModuleRelation.setRoleId(roleId);
                            roleModuleRelation.setModuleId(moduleId);
                            roleModuleRelationRepository.save(roleModuleRelation);
                        }
                    }
                } else {
                    //2.2 全量添加新关系
                    for (Long moduleId : moduleIdList) {
                        if (!roleModuleRelationRepository.existsByRoleIdAndModuleId(roleId, moduleId)) {
                            RoleModuleRelation roleModuleRelation = new RoleModuleRelation();
                            roleModuleRelation.setRoleId(roleId);
                            roleModuleRelation.setModuleId(moduleId);
                            roleModuleRelationRepository.save(roleModuleRelation);
                        }
                    }
                }
            }
        }
    }
}
